package moltencore.network.game;

import moltencore.game.Field;
import moltencore.game.IGameEventListener;
import moltencore.game.Game;
import moltencore.game.Player;
import moltencore.game.bubble.Bubble;
import moltencore.network.protocol.*;
import spark.math.Vector2;
import spark.network.ServerSender;

import java.util.Collection;
import java.util.LinkedList;

public class GameEventDistributor implements IGameEventListener {
	private ServerSender sender;

	public GameEventDistributor(ServerSender sender) {
		this.sender = sender;
	}

	@Override
	public void playerJoinedGame(Player player) {
		PlayerJoinedGame packet = new PlayerJoinedGame(player);
		sender.propagate(packet);
	}


	@Override
	public void playerJoinedTeam(Player player, int teamIndex) {
		PlayerJoinedTeam packet = new PlayerJoinedTeam(player, teamIndex);
		sender.propagate(packet);
	}

	@Override
	public void gameReadyToStart(Game game) {
		//notify all players about it
		GameStarted gameStart = new GameStarted();
		sender.propagate(gameStart);
	}

	@Override
	public void newCannonTarget(long cannonOwnerClientId, Vector2 target) {
		CannonNewTargetDirection packet = new CannonNewTargetDirection();
		packet.setAimVector(target);
		packet.setClientId(cannonOwnerClientId);
		sender.propagate(packet);
	}

	@Override
	public void bubbleFixated(Bubble bubble, long fieldId) {
		BubbleFixatedNotification packet = new BubbleFixatedNotification();
		packet.setBubbleData(new BubbleData(bubble, fieldId));
		packet.getBubbleData().getVelocity().zero();
		sender.propagate(packet);
	}

	@Override
	public void bubblePopped(Bubble bubble, long fieldId) {
		BubblePoppedNotification packet = new BubblePoppedNotification();
		packet.setBubbleData(new BubbleData(bubble, fieldId));
		packet.getBubbleData().getVelocity().zero();
		sender.propagate(packet);
	}

	@Override
	public void bubbleNext(Bubble bubble, long fieldId, long clientId) {
		BubbleNextNotification packet = new BubbleNextNotification();
		packet.setBubbleData(new BubbleData(bubble, fieldId));
		sender.propagate(packet);
	}

	@Override
	public void gameStarting(Game game, int teamSize) {
		GameStartingNotification packet = new GameStartingNotification();
		packet.setTeamSize(teamSize);
		LinkedList<FieldLayout> fieldLayouts = new LinkedList<FieldLayout>();
		for(Player player : game.getCurrentPlayers()) {
			packet.getPlayerFieldPairs().add(new Long[] { player.getClientId(), player.getField().getFieldId() });
			boolean layoutAlreadyContained = false;
			for(FieldLayout fieldLayout : fieldLayouts) {
				if(fieldLayout.getFieldId() == player.getField().getFieldId()) {
					layoutAlreadyContained = true;
				}
			}
			if(!layoutAlreadyContained) {
				fieldLayouts.add(new FieldLayout(player.getField()));
			}
		}
		sender.propagate(packet);
		for(FieldLayout fieldLayout : fieldLayouts) {
			sender.propagate(fieldLayout);
		}
	}

	@Override
	public void gameEnded(Collection<Field> winners, Collection<Field> losers) {
		GameEndedNotification packet = new GameEndedNotification();
		packet.setResultCount((byte)(winners.size() + losers.size()));
		int i = 0;
		for(Field winner : winners) {
			GameEndedNotification.Result result = new GameEndedNotification.Result();
			result.setFieldId(winner.getFieldId());
			result.setWon(true);
			packet.getResults()[i] = result;
			i++;
		}
		for(Field loser : losers) {
			GameEndedNotification.Result result = new GameEndedNotification.Result();
			result.setFieldId(loser.getFieldId());
			result.setWon(false);
			packet.getResults()[i] = result;
			i++;
		}
		sender.propagate(packet);
	}

	@Override
	public void bubbleFired(Bubble bubble, long fieldId) {
		BubbleMovingNotification packet = new BubbleMovingNotification();
		packet.setBubbleData(new BubbleData(bubble, fieldId));
		sender.propagate(packet);
	}

	@Override
	public void rowPushed(long fieldId, LinkedList<Bubble> row, Vector2 direction) {
		RowPushed packet = new RowPushed(fieldId, direction, row);
		sender.propagate(packet);
	}

	@Override
	public void ceilingPushed(long fieldId, Vector2 direction) {
		CeilingPushed packet = new CeilingPushed(fieldId, direction);
		sender.propagate(packet);
	}

	@Override
	public void newScore(long fieldId, int score){
		sender.propagate(new PlayerScoreUpdate(fieldId, score));
	}

	@Override
	public void timeLeft(float secondsLeft) {
		sender.propagate(new TimeLeft(secondsLeft));
	}
}
